﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2022-2022 LiLong                                              **
**  This file is part of BluetoothCpp.                                          **
**                                                                              **
**  BluetoothCpp is free software: you can redistribute it and/or modify        **
**  it under the terms of the GNU Lesser General Public License as published by **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  BluetoothCpp is distributed in the hope that it will be useful,             **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU Lesser General Public License for more details.                         **
**                                                                              **
**  You should have received a copy of the GNU Lesser General Public License    **
**  along with BluetoothCpp.  If not, see <https://www.gnu.org/licenses/>.      **
**********************************************************************************/
#include "Device.h"

namespace BTH
{
struct Device::Impl
{
    Address address;
    std::string name;
    bool connected { false };
    bool remembered { false };
    bool authenticated { false };
    MajorDeviceClass majorDeviceClass { MajorDeviceClass::Miscellaneous };
    unsigned char minorDeviceClass { 0 };
    ServiceClass serviceClass { None };
    std::chrono::time_point<std::chrono::system_clock> lastSeen;
    std::chrono::time_point<std::chrono::system_clock> lastUsed;
};

Device::Device() noexcept : m_impl(std::make_unique<Impl>()) {}

Device::Device(Device&& rhs) noexcept { std::swap(m_impl, rhs.m_impl); }

Device::Device(const Device& rhs) noexcept : Device() { operator=(rhs); }

Device::~Device() noexcept {}

void Device::setAddress(const Address& addr) noexcept { m_impl->address = addr; }

const Address& Device::address() const noexcept { return m_impl->address; }

void Device::setName(std::string_view name) noexcept { m_impl->name = name; }

const std::string& Device::name() const noexcept { return m_impl->name; }

bool Device::isConnected() const noexcept { return m_impl->connected; }

bool Device::isRemembered() const noexcept { return m_impl->remembered; }

bool Device::isAuthenticated() const noexcept { return m_impl->authenticated; }

Device::MajorDeviceClass Device::majorDeviceClass() const noexcept { return m_impl->majorDeviceClass; }

unsigned char Device::minorDeviceClass() const noexcept { return m_impl->minorDeviceClass; }

Device::ServiceClass Device::serviceClass() const noexcept { return m_impl->serviceClass; }

const std::chrono::time_point<std::chrono::system_clock>& Device::lastSeenTime() const noexcept { return m_impl->lastSeen; }

const std::chrono::time_point<std::chrono::system_clock>& Device::lastUsedTime() const noexcept { return m_impl->lastUsed; }

void Device::setConnected(bool connected) noexcept { m_impl->connected = connected; }

void Device::setRemembered(bool remembered) noexcept { m_impl->remembered = remembered; }

void Device::setAuthenticated(bool authenticated) noexcept { m_impl->authenticated = authenticated; }

void Device::setMajorDeviceClass(MajorDeviceClass c) noexcept { m_impl->majorDeviceClass = c; }

void Device::setMinorDeviceClass(unsigned char minor) noexcept { m_impl->minorDeviceClass = minor; }

void Device::setServiceClass(ServiceClass sc) noexcept { m_impl->serviceClass = sc; }

void Device::setLastSeenTime(const std::chrono::time_point<std::chrono::system_clock>& time) noexcept { m_impl->lastSeen = time; }

void Device::setLastUsedTime(const std::chrono::time_point<std::chrono::system_clock>& time) noexcept { m_impl->lastUsed = time; }

Device& Device::operator=(Device&& rhs) noexcept
{
    std::swap(m_impl, rhs.m_impl);
    return *this;
}

Device& Device::operator=(const Device& rhs) noexcept
{
    *m_impl = *rhs.m_impl;
    return *this;
}

BTH_EXPORT std::basic_ostream<char, std::char_traits<char>>& operator<<(std::basic_ostream<char, std::char_traits<char>>& stream,
                                                                        BTH::Device::MajorDeviceClass major)
{
    switch (major)
    {
    case BTH::Device::MajorDeviceClass::Miscellaneous:
        stream << "Miscellaneous";
        break;
    case BTH::Device::MajorDeviceClass::Computer:
        stream << "Computer";
        break;
    case BTH::Device::MajorDeviceClass::Phone:
        stream << "Phone";
        break;
    case BTH::Device::MajorDeviceClass::AccessPoint:
        stream << "AccessPoint";
        break;
    case BTH::Device::MajorDeviceClass::AudioVedio:
        stream << "AudioVedio";
        break;
    case BTH::Device::MajorDeviceClass::Peripheral:
        stream << "Peripheral";
        break;
    case BTH::Device::MajorDeviceClass::Imaging:
        stream << "Imaging";
        break;
    case BTH::Device::MajorDeviceClass::Wearable:
        stream << "Wearable";
        break;
    case BTH::Device::MajorDeviceClass::Toy:
        stream << "Toy";
        break;
    case BTH::Device::MajorDeviceClass::Health:
        stream << "Health";
        break;
    case BTH::Device::MajorDeviceClass::Uncategorized:
        stream << "Uncategorized";
        break;
    default:
        break;
    }
    return stream;
}
} // namespace BTH
